package cc.sunni.activiti.exception;

import cc.sunni.activiti.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.sql.SQLException;

/**
 * 异常处理器
 */
@RestControllerAdvice
@Slf4j
public class RRExceptionHandler {

    /**
     * 处理自定义异常
     * 使用@ResponseStatus改变响应的状态码
     */
    @ExceptionHandler(RRException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R error(RRException e) {
        R r = new R();
        r.put("code", e.getCode());
        r.put("msg", e.getMessage());
        r.put("success", false);
        return r;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public R error(NoHandlerFoundException e) {
        log.error(e.getMessage(), e);
        return R.error(404, "路径不存在，请检查路径是否正确");
    }

    /**
     * 参数合法性校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R error(MethodArgumentNotValidException e) {
        FieldError fieldError = e.getBindingResult().getFieldError();
        assert fieldError != null;
        log.error("参数合法性校验异常---{}[{}]", fieldError.getField(), fieldError.getDefaultMessage());
        return R.error(fieldError.getDefaultMessage());
    }

    /**
     * 参数合法性校验异常-类型不匹配
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public R error(MethodArgumentTypeMismatchException e) {
        log.error("参数合法性校验异常-类型不匹配---{}", e.getMessage());
        return R.error(e.getMessage());
    }

    /**
     * 参数绑定异常
     */
    @ExceptionHandler(BindException.class)
    public R error(BindException e) {
		FieldError fieldError = e.getBindingResult().getFieldError();
		assert fieldError != null;
        log.error("参数绑定异常---{}[{}]", fieldError.getField(), fieldError.getDefaultMessage());
		return R.error(fieldError.getDefaultMessage());
    }

    /**
     * Sql语法错误
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public R error(BadSqlGrammarException e) {
        log.error(e.getMessage());
        return R.error("sql语法错误");
    }

    /**
     * Sql语法错误
     */
    @ExceptionHandler(SQLException.class)
    public R error(SQLException e) {
        log.error(e.getMessage());
        return R.error("sql语法错误");
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    public R error(DataIntegrityViolationException e) {
        log.error(e.getMessage());
        return R.error("sql语法错误");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public R error(DuplicateKeyException e) {
        log.error(e.getMessage(), e);
        return R.error("数据库中已存在该记录");
    }

    @ExceptionHandler(Exception.class)
    public R error(Exception e) {
        log.error(e.getMessage(), e);
        return R.error();
    }
}
